package com.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;


import com.util.GenericClass;

public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
	private Class<?> entityClass=GenericClass.getGenericClass(this.getClass());
	
	@Resource(name="sessionFactory")
	public void setSessionFactory4Spring(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	
	public void setEntityClass(Class<?> entityClass){
		this.entityClass=entityClass;
	}

	public void save(T entity) {
		// TODO Auto-generated method stub
		this.getHibernateTemplate().save(entity);
	}

	public void update(T entity) {
		// TODO Auto-generated method stub
		this.getHibernateTemplate().update(entity);
	}

	@SuppressWarnings("unchecked")
	public T findById(Serializable id) {
		// TODO Auto-generated method stub
		return (T) this.getHibernateTemplate().get(entityClass, id);
	}

	public void deleteByIds(Serializable... ids) {
		// TODO Auto-generated method stub
		if(ids!=null&&ids.length>0){
			for(Serializable id:ids){
				Object entity=this.getHibernateTemplate().get(entityClass, id);
				if(entity!=null){
					this.getHibernateTemplate().delete(entity);
				}
			}
		}
	}

	public void deleteAll(Collection<T> entities) {
		// TODO Auto-generated method stub
		this.getHibernateTemplate().deleteAll(entities);
	}
	
	@SuppressWarnings({"rawtypes","unchecked"})
	public List<T> findByCondition(String whereHql,final Object[] params,
			Map<String, String> orderBy, final boolean cacheable) {
		// TODO Auto-generated method stub
		String hql="select o from "+entityClass.getSimpleName()+" o where 1=1 ";
		
		if(StringUtils.isNotBlank(whereHql)){
			hql=hql+whereHql;
		}
		
		String orderByStr=this.buildOrderBy(orderBy);
		hql=hql+orderByStr;
		final String _hql=hql;
		
		List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException,SQLException{
				Query query=session.createQuery(_hql);
				if(cacheable){
					query.setCacheable(true);
				}
				setParams(query,params);
				return query.list();
			}

		});
		return list;
	}

	private String buildOrderBy(Map<String, String> orderBy) {
		// TODO Auto-generated method stub
		StringBuffer buf=new StringBuffer();
		if(orderBy!=null&&!orderBy.isEmpty()){
			buf.append(" order by ");
			for(Map.Entry<String,String> em : orderBy.entrySet()){
				buf.append(em.getKey() + " "+ em.getValue()+",");
			}
			buf.deleteCharAt(buf.length()-1);
		}
		return buf.toString();
	}

	protected void setParams(Query query, Object[] params) {
		// TODO Auto-generated method stub
		if(params!=null&&params.length>0){
			for(int i=0;i<params.length;i++){
				query.setParameter(i, params[i]);
			}
		}
	}

	public List<T> findByCondition(String whereHql, Object[] params,
			boolean cacheable) {
		// TODO Auto-generated method stub
		return this.findByCondition(whereHql, params, null, cacheable);
	}


	public List<T> findByCondition(Map<String, String> orderBy,
			boolean cacheable) {
		// TODO Auto-generated method stub
		return this.findByCondition(null, null, orderBy, cacheable);
	}

	public List<T> findAll(boolean cacheable) {
		// TODO Auto-generated method stub
		return this.findByCondition(null, null, null, cacheable);
	}

	public T findFirstByCondition(String whereHql, Object[] params,
			boolean cacheable) {
		// TODO Auto-generated method stub
		List<T> list = this.findByCondition(whereHql,params, cacheable);
		if(list!=null&&list.size()>0){
			return list.get(0);
		}
		return null;
	}
	
	@SuppressWarnings({"rawtypes","unchecked"})
	public List<T> findByConditionWithPaging(String whereHql,final Object[] params,
			Map<String, String> orderBy,final int offset,final int length) {
		// TODO Auto-generated method stub
		String hql="select o from "+entityClass.getSimpleName()+" o where 1=1 ";
		
		if(StringUtils.isNotBlank(whereHql)){
			hql=hql+whereHql;
		}
		
		String orderByStr=this.buildOrderBy(orderBy);
		hql=hql+orderByStr;
		final String _hql=hql;
		
		List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException,SQLException{
				Query query=session.createQuery(_hql);
				query.setFirstResult(offset);
				query.setMaxResults(length);
				setParams(query,params);
				return query.list();
			}

		});
		return list;
	}
	
	@SuppressWarnings({"rawtypes","unchecked"})
	public int getRowCont(String whereHql,final Object[] params) {
		// TODO Auto-generated method stub
		String hql="select count(*) from "+entityClass.getSimpleName()+" o where 1=1 ";
		if(StringUtils.isNotBlank(whereHql)){
			hql=hql+whereHql;
		}
		
		final String _hql=hql;
		
		long count = (long) this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException,SQLException{
				Query query=session.createQuery(_hql);
				setParams(query,params);
				return query.list();
			}
		});
		return (int)count;
	}
}
